package net.fltx.Ax;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public  class AxCoer {
	private AxCell[][] map;
	private int x;
	private int y;
	private int w;
	private int h;
	private int cSize;
	private boolean mod=false;//是否开启八方检测,默认4方检测
	//保存走的路线
	//private Queue<AxCell> cells=new LinkedList<AxCell>();
	private List<AxCell> cells =new ArrayList<AxCell>();
		
	public boolean isMod() {
		return mod;
	}
	public void setMod(boolean mod) {
		this.mod = mod;
	}
	//起点格子
	public AxCell pointStart;
	//当前格子
	public AxCell point;
	//终点格子
	public AxCell pointEnd;
	//最短路线
	List<AxCell> line;
	
	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getW() {
		return w;
	}

	public void setW(int w) {
		this.w = w;
	}

	public int getH() {
		return h;
	}

	public void setH(int h) {
		this.h = h;
	}

	public int getcSize() {
		return cSize;
	}

	public void setcSize(int cSize) {
		this.cSize = cSize;
	}

	public AxCoer() {
		this(0,0,15,15,20);
	}
	
	public AxCoer(int x, int y, int w, int h) {
		this(x,y,w,h,20);
	}
	

	public AxCoer(int x, int y, int w, int h, int cSize) {
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
		this.cSize = cSize;
		map=new AxCell[h][w];
		for(int r=0;r<h;r++){
			for(int c=0;c<w;c++){
				map[r][c]=new AxCell(c,r , -1, AxCell.PASSABLE, -1.0);
			}
		}
		line=new ArrayList<AxCell>();
	}

	/**
	 * 设置指定位置的格子, 并返回之前的格子
	 * @return 返回之前的格子
	 */
	public AxCell setCell(int x, int y, int step, int type, double distance){
		AxCell Oldcell=map[y][x];
		map[y][x]=new AxCell(x, y, step, type, distance);
		return Oldcell;
	}
	
	/**
	 * 设置指定位置的格子,并返回之前的格子
	 * @return 返回之前的格子
	 */
	public AxCell setCell(int x,int y,AxCell newCell){
		AxCell Oldcell=map[y][x];
		map[y][x]=newCell;
		return Oldcell;
	}
	
	/**
	 * 获取指定位置的格子
	 * @return
	 */
	public AxCell getCell(int x,int y){
		if(x<0 || x>=w || y<0 || y>=h) return null;
		return map[y][x];
	}
	
	public void setCellSize(int cSize){
		this.cSize=cSize;
	}
	
	/**
	 * 范围指定格子的周围格子
	 * @param axCell
	 * @return
	 */
	private List<AxCell> getWall(AxCell mc){
		List<AxCell> cells=new ArrayList<AxCell>();
		AxCell c=null;
		//检测四方:右,上,左,下
		if((c=getCell(mc.x+1,mc.y))!=null) cells.add(c);
		if((c=getCell(mc.x,mc.y-1))!=null) cells.add(c);
		if((c=getCell(mc.x-1,mc.y))!=null) cells.add(c);
		if((c=getCell(mc.x,mc.y+1))!=null) cells.add(c);
		if(mod){  //检测四角
			if((c=getCell(mc.x+1,mc.y-1))!=null) cells.add(c);
			if((c=getCell(mc.x-1,mc.y-1))!=null) cells.add(c);
			if((c=getCell(mc.x-1,mc.y+1))!=null) cells.add(c);
			if((c=getCell(mc.x+1,mc.y+1))!=null) cells.add(c);
		}
		return cells;
	}
	
	
	
	/**
	 * 遍历查找
	 * 
	 * @return 如果查找未结束返回0;如果查找结束,找到目标返回1并设置cells,未找到返回-1;
	 */
	public int seekOnErgodic(){
		if(point==null) {  //初始化查找
			cells.clear();
			line.clear();
			cells.add(pointStart);
			point=pointEnd;
		}
		List<AxCell> in=new ArrayList<AxCell>();
		for(AxCell c:cells){
			List<AxCell> tmp=getWall(c);
			for(AxCell e:tmp){
				if(e.step==-1 && e.type !=AxCell.IMPASSABLE){
					e.setStep(c.step+1).setDistance(pointEnd);
					in.add(e);
					if(e==pointEnd) return 1;
				}
			}
		}
		if(in.size()==0) return -1;
		cells=in;
		in=null;
		return 0;
	}
	
	
	public int seekOnAx(){
		//初始化
		if(point==null ){
			line.clear();
			cells.clear();
			point =pointStart;
		}
		List<AxCell> clist=getWall(point);
		for(AxCell e:clist){
			if(e.step==-1 && e.type !=AxCell.IMPASSABLE){
				e.setStep(point.step+1).setDistance(pointEnd);
				cells.add(e);
				if(e==pointEnd) {
					point=pointEnd;
					return 1;
				}
			}
		}
		if(cells.size()==0) return -1; //没有路走了返回-1
		//获取离终点最近的点
		point=cells.get(0);
		for(int i=1;i<cells.size();i++){
			AxCell e=cells.get(i);
			double pDis=point.distance+point.step;//AxCell.survey(point, pointStart);
			double eDis=e.distance+e.step;//AxCell.survey(e, pointStart);
			if(pDis>eDis ) {
				point=e;
			}else if(pDis==eDis && point.distance>e.distance) {
				point=e;
			}
		}
		cells.remove(point);
		return 0;
	}
	
	public boolean makeLine(){
		List<AxCell> clist=getWall(point);
		point=null;
		for(int i=0;i<clist.size();i++){
			AxCell e=clist.get(i);
			if(point==null) {
				if(e.step!=-1) point=e;
			}else if(e.step!=-1 && point.step>e.step){ //&& point.distance>e.distance
				point=e;
			}
		}
		line.add(point);
		//System.out.println(point);
		
		if(point==pointStart) return true;
		return false;
	}
	
	
	/**
	 * 画经过格子,这个方法要放在画板中
	 * @param g
	 */
	public void draw(Graphics g){
		for(int r=0;r<h;r++){
			for(int c=0;c<w;c++){
				AxCell cell=map[r][c];
				g.setColor(new Color(0xf8f8f8));
				if(cell.type==AxCell.PASSABLE && cell.step>0) {
					g.setColor(new Color(0xaaaaaa));
				}
				if(point!=null && cell==point)g.setColor(new Color(0xffff00));
				if(cell.type==AxCell.IMPASSABLE) g.setColor(new Color(0x0));
				if(line.contains(cell))g.setColor(new Color(0xffff));
				if(cell.type==AxCell.START) g.setColor(new Color(0x00ff00));
				if(cell.type==AxCell.END) g.setColor(new Color(0xff0000));
				g.fillRect(x+cSize*c, y+cSize*r, cSize, cSize);
				if(cell.step!=-1){
					g.setColor(new Color(0));
					g.drawString(cell.step+"", x+cSize*c, y+cSize*r+cSize);
				}
				g.setColor(new Color(0xf0f080));
				g.drawRect(x+cSize*c, y+cSize*r, cSize, cSize);
			}
		}
	}
	
	/**
	 * 清除表格
	 */
	public void clear(){
		map=new AxCell[h][w];
		point=null;
		pointEnd=null;
		pointStart=null;
		for(int r=0;r<h;r++){
			for(int c=0;c<w;c++){
				map[r][c]=new AxCell(c,r , -1, AxCell.PASSABLE, -1.0);
			}
		}
	}
	
	/**
	 * 清除路迹
	 */
	public void clearEx(){
		point=null;
		pointEnd.step=-1;
		pointStart.step=-1;
		line.clear();
		for(int r=0;r<h;r++){
			for(int c=0;c<w;c++){
				map[r][c].step=-1;
			}
		}
	}
	
	/**
	 * 通过鼠标指针获取格子位置
	 * @param m 鼠标指针
	 * @return 格子位置的指针
	 */
	public Point getCellPoint(Point m ){
		int cx=(m.x-m.x%cSize)/cSize;
		int cy=(m.y-m.y%cSize)/cSize;
		return new Point(cx>=w?w-1:cx, cy>=h?h-1:cy);
	}
	
	
}
